/**
 * Chart View
 *
 * Encapsulates all behavior of the Chart View
 *
 *
 * @author Jon Leckman
 * @version 1.00 2012/3/26
 */

package SOEN_Phase_3;

// *** Import SWING GUI libraries *** //
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JButton;
import javax.swing.JTextField;

import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Graphics;
import java.awt.Color;

import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;


public class ChartView extends JFrame{

//privately held array of tasks
private Task[] tasks;

//helpers for when iterating over the tasks to collect data
private int totalTime, totalTimeComplete, totalPreTime;

//helper bool for visbility
private boolean show;

	/**
     * Constructor for ChartView
     *
     * @param Object[] The array of Objects (should be tasks) to use for the display
     **/
    public ChartView(Object[] x)
    {

   		// Set window title
        setTitle("Chart View");

   		// Set window size
        setSize(900, 200);

   		// Set layout
		GridBagLayout grid = new GridBagLayout();
   		getContentPane().setLayout(grid);
   		getContentPane().setBackground(Color.WHITE);

   		//initializors
    	totalTime = totalTimeComplete = totalPreTime = 0;
    	tasks = new Task[0];

		//hide on closure rather than close
		addWindowListener(new java.awt.event.WindowAdapter()
		{
    		public void windowClosing(WindowEvent e)
    		{
        		setShow(false);
    		}
		});

		show = false;
		super.setVisible(false);

    }


	public void setShow(boolean x){
		show = x;
		super.setVisible(show);
	}


    /**
     * chartUpdate(Object[] x)
     *
     * The only public method, it is used to set up the Task array and then loop through the display process
     *
     * @param Object[] The array of Objects (should be tasks) to use for the display
     * @return void
     */
    public void chartUpdate(Object[] x)
    {
    	super.hide();

		//clear the frame
		getContentPane().removeAll();

    	//Reinitialize the task array
    	tasks = new Task[x.length];

		//Translate the array of Objects into an arrray of tasks for slightly better ease of use
    	for (int i=0; i<x.length ;i++)
    	{
    		tasks[i] = new Task( ((Task)x[i]).getID(), ((Task)x[i]).getDuration(), ((Task)x[i]).getTitle(), ((Task)x[i]).getAssignee(), ((Task)x[i]).getAssigneeID(), ((Task)x[i]).getTimeInvested(), ((Task)x[i]).getCompletion(), ((Task)x[i]).getSubtasks(), ((Task)x[i]).getDependencies()  );
    		tasks[i].setParent(((Task)x[i]).getParent());
    	}

 		//Main display loop begins
		for (Task task: tasks){

			//Reinitialize counters for each master task
			totalTime = 0;
			totalTimeComplete = 0;
			totalPreTime = 0;

			//We perform display functions beginning if and only if the task is a master task
			if ( task.getParent() == null  )
			{

				//Get the total time needed for the tree of tasks
				//Get the amount of time completed for the tree of tasks
				totalTime = getTaskTimeTotal(task);
				totalTimeComplete = getCompleteTime(task);

				//If there are no subtasks the only display needed is a header type
				if( task.getSubtasks().isEmpty() )
				{
					displayHeader(task);
				}

				//If there are subtasks both a header and a subtask display are needed
				else
				{
					displayHeader(task);
					displayTask(task);
				}
			}
		}

		if(show) super.show();

	}


    /**
     * displayHeader(Task t)
     *
     * Updates the frame for a master task
     *
     * @param Task a task with which to update the display
     * @return void
     */
	private void displayHeader(Task t)
	{
		//Set up and add the label for the master task
		JLabel label = new JLabel("Task:"+t.getTitle()+"  Total Time:" +totalTimeComplete+"/"+totalTime+" hrs");
		GridBagConstraints c = new GridBagConstraints();
		c.weightx = .1;
		c.fill = GridBagConstraints.HORIZONTAL;
		getContentPane().add(label, c);

		//Set up and add the graph bar for the master task
		c.weightx = 2;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridwidth = GridBagConstraints.REMAINDER;

		//Simple calculations to scale the time invested and total times to the bar width of 500
		double completed = totalTimeComplete;
		double remaining = totalTime - totalTimeComplete;
		completed = ( (completed/totalTime)*500 );
		remaining = ( (remaining/totalTime)*500 );

		//Finally create and add the bar created with the scaled values
		getContentPane().add(new RectPanel(0, (int)completed, (int)remaining ) , c) ;

	}




    /**
     * updateDisplay(Task t)
     *
     * Updates the frame for a sub task
     *
     * @param Task a task with which to update the display
     * @return void
     */
	private void updateDisplay(Task t)
	{

		//Set up and add the label for the subtask task
		JLabel label = new JLabel("Subtask:" + t.getTitle() + "  Sub Time:" + t.getTimeInvested()+"/"+ t.getDuration()+" hrs");
		GridBagConstraints c = new GridBagConstraints();
		c.weightx = .1;
		c.fill = GridBagConstraints.HORIZONTAL;
		getContentPane().add(label, c);

		//Set up and add the graph bar for the sub task
		c.weightx = 2;
		c.fill = GridBagConstraints.HORIZONTAL;
		c.gridwidth = GridBagConstraints.REMAINDER;

		//Simple calculations to scale the time invested and total times to the bar width of 500
		double pretime = ((totalPreTime * 500 ) / totalTime);
		double completed = ((t.getTimeInvested() * 500 ) / totalTime);
		double remaining = (( (t.getDuration() - t.getTimeInvested() ) * 500 ) / totalTime);

		//Finally create and add the bar created with the scaled values
		getContentPane().add(new RectPanel( ((int)pretime), ((int)completed), ((int)remaining)) , c) ;
	}

    /**
     * displayTask(Task t)
     *
     * Recursive loop to parse through a tree of tasks and display each one in turn
     *
     * @param Task A nested task to travel
     * @return void
     */
	private void displayTask(Task t)
	{
		if ( t.getSubtasks().isEmpty() )
		{
			updateDisplay(t);
			totalPreTime += t.getDuration();
		}
		else
		{
			displaySubTask(t);
		}
	}

	 /**
     * displaySubTask(Task t)
     *
     * Helper for displayTask, should never be called anywhere else
     *
     * @param Task A nested task to travel
     * @return void
     */
	private void displaySubTask(Task t)
	{
		updateDisplay(t);
		totalPreTime += t.getDuration();

		for (Task subTask : t.getSubtasks())
		{
			displayTask(subTask);
		}
	}

    /**
     * getTaskTimeTotal(Task t)
     *
     * Recursive loop to parse through a tree of tasks and sum the total time needed to complete it
     *
     * @param Task A nested task to travel
     * @return int The total time needed to complete the tree of tasks
     */
	private int getTaskTimeTotal(Task t)
	{
		if ( t.getSubtasks().isEmpty() )
		{
			return t.getDuration();
		}
		else
		{
			return getSubTaskTimeTotal(t);
		}
	}

    /**
     * getSubTaskTimeTotal(Task t)
     *
     * Helper for the getTaskTimeTotal loop, should never be called anywhere else
     *
     * @param Task A nested task to travel
     * @return int A sub-set of the time needed to complete the tree of tasks
     */
	private int getSubTaskTimeTotal(Task t)
	{
		int x = t.getDuration();
		for (Task subTask : t.getSubtasks() )
		{
			x += getTaskTimeTotal(subTask);
		}
		return x;
	}


	 /**
     * getCompleteTime(Task t)
     *
     * Recursive loop to parse through a tree of tasks and return the total time invested across all tasks
     *
     * @param Task A nested task to travel
     * @return int The time invested across all tasks
     */
	private int getCompleteTime(Task t)
	{
		if ( t.getSubtasks().isEmpty() )
		{
			return t.getTimeInvested();
		}
		else
		{
			return getSubCompleteTime(t);
		}
	}

	 /**
     * getSubCompleteTime(Task t)
     *
     * Helper for the getCompleteTime loop, should never be called anywhere else
     *
     * @param Task A nested task to travel
     * @return int A sub-set of the time invsted in the tree of tasks
     */
	private int getSubCompleteTime(Task t)
	{
		int x = t.getTimeInvested();
		for (Task subTask : t.getSubtasks() )
		{
			x += getCompleteTime(subTask);
		}
		return x;
	}


	 /**
     * RectPanel
     *
     * JPanel extended subclass, is created with appropriate values and returns a width 500 bar colored
     * to indicate progress over a task
     */

	private class RectPanel extends JPanel
	{

	//width of the 4 bar sections, grey, green, red, grey
		private int a,b,c,d;

	 /**
     * Constructor for RectPanel
     *
     * @param int Width of 1st panel
     * @param int Width of 2nd panel
     * @param int Width of 3rd panel
     **/
		public RectPanel(int o, int g, int r)
		{
			a=o;
			b=g;
			c=r;
			d=500-(o+g+r);
			setSize(500,25);
			setVisible(true);
		}

	 /**
     * paintComponent
     *
     * Overridden paintComponent, adds 4 colored rectangles
     *
     * @param Graphics The JPanel's graphics
     * @return void
     */
		public void paintComponent(Graphics g)
		{
			super.paintComponent(g);
			g.setColor(Color.GRAY);
			g.fillRect(0 , 0,  a, 25);
			g.setColor(Color.GREEN);
			g.fillRect(a, 0, b, 25);
			g.setColor(Color.RED);
			g.fillRect(a+b, 0, c, 25);
			g.setColor(Color.GRAY);
			g.fillRect(a+b+c, 0, d, 25);
		}
	}
}